﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD {
    /// <summary>
    /// コンポジットモード
    /// </summary>
    /// <remarks>
    /// <see cref="CompositeMode"/>はシェーダーを実行後の処理をカプセル化したアピアランスの構成要素です。
    /// デプステストおよびカラーバッファー、デプスバッファーへの書き込みとそのブレンド方式を制御します。
    /// </remarks>
    public class CompositeMode : Object {
        #region Field
        uint colorWriteMask;
        uint depthWriteMask;
        bool depthTestEnabled;
        DepthComparisonFunction depthComparisonFunction;
        ColorBlendFunction colorBlendFunction;
        #endregion

        #region Constructor
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public CompositeMode () {
            this.colorWriteMask = 0xffffffff;
            this.depthWriteMask = 0xffffffff;
            this.depthTestEnabled = true;
            this.depthComparisonFunction = DepthComparisonFunction.LessEqual;
            this.colorBlendFunction = ColorBlendFunction.Replace;
        }
        #endregion

        #region Property
        /// <summary>
        /// デプステストの有効無効フラグ
        /// </summary>
        public bool IsDepthTestEnabled {
            get { return depthTestEnabled; }
        }

        /// <summary>
        /// デプステストで使用される比較関数
        /// </summary>
        public DepthComparisonFunction DepthComparisonFunction {
            get { return depthComparisonFunction; }
        }

        /// <summary>
        /// デプスバッファーへの書き込みマスク
        /// </summary>
        /// <remarks>
        /// マスクのビットが立っているチャンネルのみ書き込み可能です。
        /// </remarks>
        public uint DepthWriteMask {
            get { return depthWriteMask; }
        }



        /// <summary>
        /// カラーバッファーへのブレンドモード
        /// </summary>
        /// <remarks>
        /// </remarks>
        public ColorBlendFunction ColorBlendFunction {
            get { return colorBlendFunction; }
        }

     
        /// <summary>
        /// カラーバッファーへの書き込みマスク
        /// </summary>
        /// <remarks>
        /// </remarks>
        public uint ColorWriteMask {
            get { return colorWriteMask; }
        }



        /// <summary>
        /// このオブジェクトが参照する全DDDオブジェクトを列挙する列挙子
        /// </summary>
        /// <remarks>
        /// 参照にnullは含まれません。同一のオブジェクトが複数出現する可能性があります。
        /// </remarks>
        public override IEnumerable<Object> References {
            get {
                return base.References;
            }
        }
        #endregion

        #region Method

        /// <summary>
        /// カラーバッファーへのブレンド方式を変更します
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="func">ブレンド方式</param>
        public void SetColorBlendFunction (ColorBlendFunction func) {
            this.colorBlendFunction = func;
        }

    

        /// <summary>
        /// カラーバッファーへの書き込みマスクをセットします
        /// </summary>
        /// <remarks>
        /// このメソッドは原則<see cref="SetColorMask(int,uint)"/>と同じですが、
        /// 必ずカラーバッファー0への書き込みになります。
        /// </remarks>
        /// <param name="mask">マスク</param>
        public void SetColorMask (uint mask) {
            this.colorWriteMask = mask;
        }



        /// <summary>
        /// デプスバッファーへの書き込みマスクをセットします
        /// </summary>
        /// <remarks>
        /// マスクは1チャネルのみで0x00か0xFFで指定します。
        /// 0x00の時書き込み禁止でそれ以外の時(0xFFを推奨)に書き込み可能です。
        /// </remarks>
        /// <param name="mask">マスク</param>
        public void SetDepthMask (uint mask) {
            this.depthWriteMask = mask;
        }

        /// <summary>
        /// デプステストの有効無効を変更します
        /// </summary>
        /// <remarks>
        /// デプステストを無効にすると同時にデプスバッファーへの書き込みも無効化されます(OpenGLの仕様です)。
        /// </remarks>
        /// <param name="enable">有効(true)、無効(false)</param>
        public void SetDepthTestEnable (bool enable) {
            this.depthTestEnabled = enable;
        }

        /// <summary>
        /// デプステストで使用される比較関数のセット
        /// </summary>
        /// <param name="func">比較関数"</param>
        public void SetDepthComparisonFunction (DepthComparisonFunction func) {
            this.depthComparisonFunction = func;
        }

        /// <summary>
        /// 現在のオブジェクトの状態を表す文字列を返します。
        /// </summary>
        /// <returns>現在のオブジェクトを説明する文字列</returns>
        public override string ToString () {
            return string.Format ("CompositeMode: DepthTest={0}, DepthComparison={1}, DepthWriteMask={2}, ColorBlend={3}, ColorWriteMask={4}",
                IsDepthTestEnabled, DepthComparisonFunction, DepthWriteMask, ColorBlendFunction, ColorWriteMask);
        }

        #endregion
    }
}
